Components with hierarchy#

image0

You can define some components (waveguides, bends, couplers) as a stand alone components, with basic input parameters (width, length, radius …)

Then you can re-use those components in a more complex hiearchical components.

gdsfactory does this by passing the higher level component with the lower level functions to build the components.

You can customize any of the functions thanks to functools.partial

[1]:
import gdsfactory as gf
gf.CONF.plotter = 'holoviews'
2022-03-03 06:45:00.422 | INFO     | gdsfactory.config:<module>:52 - Load '/home/runner/work/gdsfactory/gdsfactory/gdsfactory' 4.3.0
[2]:
@gf.cell
def bend_with_straight(
    bend=gf.components.bend_euler,
    straight=gf.components.straight,
) -> gf.Component:
    c = gf.Component()
    b = bend()
    s = straight()

    bref = c << b
    sref = c << s

    sref.connect("o2", bref.ports["o2"])
    c.info['length'] = b.info['length'] + s.info['length']
    return c


c = bend_with_straight()
print(c.metadata.info.length)
c.plot()
26.637
[2]:

Lets customize the functions that we pass. For example, we want to increase the radius of the bend from the default 10um to 20um.

[3]:
c = gf.components.bend_circular()
c.plot()
[3]:

functools.partial#

Partial lets you define different default parameters for a function, so you can modify the settings for the child cells.

[4]:
from functools import partial
[5]:
bend20 = partial(gf.components.bend_circular, radius=20)
b = bend20()
b.plot()
[5]:
[6]:
type(bend20)
[6]:
functools.partial
[7]:
bend20.func.__name__
[7]:
'bend_circular'
[8]:
bend20.keywords
[8]:
{'radius': 20}
[9]:
b = bend_with_straight(bend=bend20)
print(b.metadata.info.length)
b.plot()
41.416
[9]:
[10]:
# You can still modify the bend to have any bend radius
b3 = bend20(radius=10)
b3.plot()
[10]:

PDK custom fab#

You can define a new PDK by creating function that customize partial parameters of the generic functions.

Lets say that this PDK uses layer (41, 0) for the pads (instead of the layer used in the generic pad function).

You can also access functools.partial from gf.partial

[11]:
import gdsfactory as gf

pad = gf.partial(gf.components.pad, layer=(41, 0))
[12]:
c = pad()
c.plot()
[12]:

Composing functions#

You can combine more complex functions out of smaller functions.

Lets say that we want to add tapers and grating couplers to a wide waveguide.

[13]:
c1 = gf.components.straight()
c1.plot()
[13]:
[14]:
straight_wide = gf.partial(gf.components.straight, width=3)
c3 = straight_wide()
c3.plot()
[14]:
[15]:
c1 = gf.components.straight(width=3)
c1.plot()
[15]:
[16]:
c2 = gf.add_tapers(c1)
c2.plot()
[16]:
[17]:
c2.metadata_child.changed # You can still access the child metadata
[17]:
{'width': 3}
[18]:
c3 = gf.routing.add_fiber_array(c2, with_loopback=False)
c3.plot()
[18]:
[19]:
c3.metadata_child.changed # You can still access the child metadata
[19]:
{'width': 3}

Lets do it with a single step thanks to toolz.pipe

[20]:
import toolz

add_fiber_array = gf.partial(gf.routing.add_fiber_array, with_loopback=False)
add_tapers = gf.add_tapers

# pipe is more readable than the equivalent add_fiber_array(add_tapers(c1))
c3 = toolz.pipe(c1, add_tapers, add_fiber_array)
c3.plot()
[20]:

we can even combine add_tapers and add_fiber_array thanks to toolz.compose or toolz.compose

For example:

[21]:
add_tapers_fiber_array = toolz.compose_left(add_tapers, add_fiber_array)
c4 = add_tapers_fiber_array(c1)
c4.plot()
[21]:

is equivalent to

[22]:
c5 = add_fiber_array(add_tapers(c1))
c5.plot()
[22]:

as well as equivalent to

[23]:
add_tapers_fiber_array = toolz.compose(add_fiber_array, add_tapers)
c6 = add_tapers_fiber_array(c1)
c6.plot()
[23]:

or

[24]:
c7 = toolz.pipe(c1, add_tapers, add_fiber_array)
c7.plot()
[24]:
[25]:
c7.metadata_child.changed # You can still access the child metadata
[25]:
{'width': 3}
[26]:
c7.metadata.child.child.name, c7.metadata.child.child.function_name
[26]:
('straight_d4f9e1ed', 'straight')
[27]:
c7.metadata.child.name, c7.metadata.child.function_name
[27]:
('straight_d4f9e1ed_add_t_d61de773', 'add_tapers')
[28]:
c7.metadata.name, c7.metadata.function_name
[28]:
('straight_d4f9e1ed_add_t_32340410', 'add_fiber_array')
[29]:
c7.metadata.changed.keys()
[29]:
dict_keys(['component', 'with_loopback'])
[ ]: